package com.lukamikec.kmap;

import java.util.ArrayList;
import java.util.HashMap;


public class kmap_expr
{	
	public static String zag = "(", mog = "<>", nuz = "[]", non = "!", et = "*",
			vel = "+", pog = "->", dpog = "<->", zagg = ")", propslovo = "A";
	//public String.get() ch_str = { zag, mog, nuz, non };
	//public String.get() ch_mdl = { et, vel, pog, dpog };
	//public String.get() ch_cls = { zagg };

	public String tip;
	public int boxed_atom_level = -1;

	public kmap_expr lexpr, rexpr;
	public String slovo;

	public kmap_expr() { }
	public kmap_expr(kmap_scanner s, String roditelj) throws Exception
	{
		parse( s, roditelj);
	}

	void parse( kmap_scanner str, String roditelj) throws Exception
	{
		if (str.eof())
			throw new Exception("Neocekivan kraj (previše ili premalo zagrada?)");

		tip = str.get();
		if (tip == propslovo)
		{
			slovo = str.get_pojavak();
		}
		else
			lexpr = new kmap_expr( str, tip);

		if (str.eof())
			return;

		String tok = str.peek();
		do
		{
			if (tok == zagg)
			{
				if (tip == zag)
					str.get();
				else
					return;
			}
			if (str.eof())
				return;

			tok = str.peek();
		} while (tok == zagg);
		
		if (roditelj == mog || roditelj == nuz || roditelj == non)
			return; // citamo samo prvi znak u slucaju ^

			


			// tip je bio pogresno pretpostavljen pa dodamo novi layer za lexpr:

				String stari_tip = tip;
			tip = str.get(); // isto što = tok

			kmap_expr x = new kmap_expr();
			x.tip = stari_tip;
			x.slovo = slovo;
			x.boxed_atom_level = boxed_atom_level;
			x.lexpr = lexpr;

			lexpr = x; // c# i erence -.-

			rexpr = new kmap_expr( str, tip);

			if (str.eof())
				return;

			tok = str.peek();

			if (tok == zagg)
			{
				if (tip == zag)
					str.get();
				return;
			}

			return;
	}
	
	public void box_atom()
	{
		if (tip == "A")
			boxed_atom_level = 0;
		
		if (lexpr != null)
		{
			lexpr.box_atom();
			if (lexpr.boxed_atom_level != -1 && tip == nuz)
			{
				slovo = lexpr.slovo;
				boxed_atom_level = lexpr.boxed_atom_level + 1;
			}
		}
		if (rexpr != null)
			rexpr.box_atom();
	}

	public ArrayList<String> get_vars()
	{
		ArrayList<String> ret = new ArrayList<String>();
		if (tip == propslovo)
			ret.add(slovo);
		else
		{
			ret = lexpr.get_vars();
			if (rexpr != null)
			{
				ArrayList<String> __nja = rexpr.get_vars();
				for (String item : __nja)
					if (!ret.contains(item))
						ret.add(item);
			}
		}
		return ret;
	}
	
	boolean eval(HashMap<String, Boolean> memory) 
	{
		if (tip == zag)
			return lexpr.eval(memory);
		if (tip == propslovo)
			return memory.get(slovo);
		if (tip == non)
			return !lexpr.eval(memory);
		if (tip == vel)
			return lexpr.eval(memory) || rexpr.eval(memory);
		if (tip == et)
			return lexpr.eval(memory) && rexpr.eval(memory);
		
		return true;
	}
	
	public String draw()
	{
		
		if (tip ==  propslovo)
			return slovo;
		if (tip ==  zag)
			return "(" + lexpr.draw() + ")";
		if (tip ==  mog || tip == nuz || tip == non)
			return tip + lexpr.draw();
		if (tip ==  et || tip == vel || tip == pog || tip == dpog)
			return lexpr.draw() + tip + rexpr.draw();

		return "???";
	}

}

